Fix recursive lock p2m lock acquisition in POD code
authorKeir Fraser <keir.fraser@citrix.com>
Thu, 1 Oct 2009 11:29:33 +0000 (12:29 +0100)
committerKeir Fraser <keir.fraser@citrix.com>
Thu, 1 Oct 2009 11:29:33 +0000 (12:29 +0100)
The POD code can take the p2m lock from inside a lookup.  This causes
a crash if anyone calls gfn_to_mfn* with the p2m lock held, which is
quite a few places.  Make the POD code understand that it may be
called with the lock held, and DTRT about talking or releasing it.

Signed-off-by: Tim Deegan <Tim.Deegan@citrix.com>
xen/arch/x86/mm/p2m.c

index 10021b7102f7ac4d899c030abcbc95e29afc72d5..77ed7f2ca52397eb4edae169f464f10603072ebd 100644 (file)
@@ -1067,21 +1067,29 @@ static int p2m_pod_check_and_populate(struct domain *d, unsigned long gfn,
                                       l1_pgentry_t *p2m_entry, int order,
                                       p2m_query_t q)
 {
+    /* Only take the lock if we don't already have it.  Otherwise it
+     * wouldn't be safe to do p2m lookups with the p2m lock held */
+    int do_locking = !p2m_locked_by_me(d->arch.p2m);
     int r;
-    p2m_lock(d->arch.p2m);
+
+    if ( do_locking )
+        p2m_lock(d->arch.p2m);
+
     audit_p2m(d);
 
     /* Check to make sure this is still PoD */
     if ( p2m_flags_to_type(l1e_get_flags(*p2m_entry)) != p2m_populate_on_demand )
     {
-        p2m_unlock(d->arch.p2m);
+        if ( do_locking )
+            p2m_unlock(d->arch.p2m);
         return 0;
     }
 
     r = p2m_pod_demand_populate(d, gfn, order, q);
 
     audit_p2m(d);
-    p2m_unlock(d->arch.p2m);
+    if ( do_locking )
+        p2m_unlock(d->arch.p2m);
 
     return r;
 }